package com.company.management.service.reward.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;

import com.company.management.constant.Constants;
import com.company.management.domain.reward.*;
import com.company.management.domain.reward.bo.PunishmentsBO;
import com.company.management.domain.reward.dto.PunishmentsAddDTO;
import com.company.management.domain.reward.dto.PunishmentsQueryDTO;
import com.company.management.domain.reward.vo.PunishmentsQueryVO;
import com.company.management.domain.reward.vo.TalentUserVO;
import com.company.management.enums.ScoreLevelFlagType;
import com.company.management.enums.ScoreModuleType;
import com.company.management.mapper.reward.PunishmentsMapper;
import com.company.management.mapper.reward.UserPunishmentsMapper;
import com.company.management.service.reward.PunishmentsService;
import com.company.management.service.reward.ScoreLevelService;
import com.company.management.service.reward.ScoreLogService;
import com.company.management.service.reward.TalentUserService;
import com.company.management.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 惩罚服务接口
 * @author: wangbin
 * @time: 2025/3/1
 **/
@Service
public class PunishmentsServiceImpl implements PunishmentsService {
    @Resource
    private PunishmentsMapper punishmentsMapper;
    @Resource
    private UserPunishmentsMapper userPunishmentsMapper;
    @Resource
    private ModelMapper modelMapper;
    @Resource
    private ScoreLogService scoreLogService;
    @Resource
    private TalentUserService talentUserService;
    @Resource
    private ScoreLevelService scoreLevelService;
    /**
     * 新增
     *
     * @param punishmentsAddDTO 新增惩罚信息
     */
    @Override
    @Transactional
    public void add(PunishmentsAddDTO punishmentsAddDTO) {
        Punishments punishments = modelMapper.map(punishmentsAddDTO, Punishments.class);
        if(StringUtils.isNotBlank(punishmentsAddDTO.getNote())){
            punishments.setNote(punishmentsAddDTO.getNote().getBytes());
        }
        //1.自定义事项保存扣分加分机制
        if(punishmentsAddDTO.checkMatter()){
            ScoreLevel scoreLevel = new ScoreLevel();
            scoreLevel.buildScoreLevel(punishmentsAddDTO.getMatter(),punishments.getPunishmentScore(),punishments.getCreateUserId());
            scoreLevel.setFlag(ScoreLevelFlagType.PUNISHMENT.getCode());
            scoreLevelService.save(scoreLevel);
            punishments.setSid(scoreLevel.getSid());
        }
        //2.校验是否是管理员
        //3.校验用户是否存在
        punishments.setPunishmentId(IdWorker.getId());
        punishments.setCreateDateTime(new Date());
        punishmentsMapper.insert(punishments);
        //4.新增关系表数据
        List<UserPunishmentsKey> userPunishmentsKeys = buildUserPunishmentsKeyList(punishmentsAddDTO.getUserIds(),punishments.getPunishmentId());
        userPunishmentsMapper.batchInsert(userPunishmentsKeys);
        //5.查询用户信息
        List<TalentUser> talentUsers = talentUserService.listByIds(punishmentsAddDTO.getUserIds());
        List<ScoreLog> scoreLogs = buildScoreLog(talentUsers, punishments);
        //6.新增奖励记录表数据
        scoreLogService.insertBatch(scoreLogs);
        //7.更新用户表分数
        talentUserService.saveOrUpdateBatch(talentUsers);
    }
    private List<ScoreLog> buildScoreLog(List<TalentUser> talentUsers,Punishments punishments){
        if (CollectionUtils.isEmpty(talentUsers)){
            return Collections.emptyList();
        }
        List<ScoreLog> scoreLogs = new ArrayList<>(talentUsers.size());
        Date date = new Date();
        for (TalentUser talentUser : talentUsers) {
            ScoreLog scoreLog = new ScoreLog();
            scoreLog.setCreateDateTime(date);
            scoreLog.setUserId(talentUser.getUserId());
            scoreLog.setFid(punishments.getPunishmentId());
            scoreLog.setFName(Constants.PUNISHMENTS_MODULE);
            Integer score = talentUser.getScore().intValue();
            scoreLog.setBeforeScore(score);
            scoreLog.setSid(punishments.getSid());
            Integer punishmentScore = punishments.getPunishmentScore();
            scoreLog.setUpdateScore(String.format(Constants.SUBTRACT,punishmentScore));
            Integer afterScore = score - punishmentScore;
            scoreLog.setAfterScore(afterScore);
            scoreLogs.add(scoreLog);
            talentUser.setScore(new BigDecimal(afterScore));
        }
        return scoreLogs;
    }

    private List<UserPunishmentsKey> buildUserPunishmentsKeyList( List<Integer> userIds, Long punishmentId) {
        if(CollectionUtils.isEmpty(userIds)){
            return Collections.emptyList();
        }
        return userIds.stream().map(userId -> {
            UserPunishmentsKey userPunishmentsKey = new UserPunishmentsKey();
            userPunishmentsKey.setUserId(userId);
            userPunishmentsKey.setPunishmentId(punishmentId);
            return userPunishmentsKey;
        }).collect(Collectors.toList());
    }


    /**
     * 根据惩罚id查询惩罚信息
     *
     * @param punishmentId 惩罚id
     */
    @Override
    public PunishmentsQueryVO findByPunishmentId(Integer punishmentId) {
        Punishments punishments = punishmentsMapper.findByPunishmentId(punishmentId);
        if (Objects.isNull(punishments)) return null;
        PunishmentsQueryVO punishmentsQueryVO = modelMapper.map(punishments, PunishmentsQueryVO.class);
        punishmentsQueryVO.setPunishmentDate(DateUtils.dateTime(punishments.getPunishmentDate()));
        if(Objects.nonNull(punishments.getNote())){
            punishmentsQueryVO.setNote(new String(punishments.getNote()));
        }
        return punishmentsQueryVO;
    }

    /**
     * 根据惩罚id查询惩罚信息
     *
     * @param punishmentsQueryDTO 用户信息
     */
    @Override
    public List<PunishmentsQueryVO> findByUserId(PunishmentsQueryDTO punishmentsQueryDTO) {
        TalentUser talentUser = talentUserService.findIsAdminByUserId(punishmentsQueryDTO.getUserId());
        if(Objects.isNull(talentUser)){
            return Collections.emptyList();
        }
        if(!talentUser.checkIsAdmin() && CollectionUtils.isEmpty(punishmentsQueryDTO.getUserIds())){
            punishmentsQueryDTO.setUserIds(Arrays.asList(punishmentsQueryDTO.getUserId()));
        }
        List<PunishmentsBO> punishments = punishmentsMapper.findByUserId(DateUtils.toDate(punishmentsQueryDTO.getStartTime()), DateUtils.toDate(punishmentsQueryDTO.getEndTime()),punishmentsQueryDTO.getUserIds());
        if(CollectionUtils.isEmpty(punishments)){
            return Collections.emptyList();
        }
        Set<Integer> createUserIds = punishments.stream().map(p -> p.getCreateUserId()).collect(Collectors.toSet());
        List<TalentUserVO> talentUserVO = talentUserService.findByCreateUseId(createUserIds);
        Map<Integer, String> userMap = talentUserVO.stream().collect(Collectors.toMap(TalentUserVO::getUserId, TalentUserVO::getUserName, (v1, v2) -> v1));
        return punishments.stream().map(p -> {
            PunishmentsQueryVO punishmentsQueryVO = modelMapper.map(p, PunishmentsQueryVO.class);
            punishmentsQueryVO.setPunishmentDate(DateUtils.dateTime(p.getPunishmentDate()));
            if(userMap.containsKey(p.getCreateUserId())){
                punishmentsQueryVO.setCreateUserName(userMap.get(p.getCreateUserId()));
            }
            if(Objects.nonNull(p.getNote())){
                punishmentsQueryVO.setNote(new String(p.getNote()));
            }
            return punishmentsQueryVO;
            }
        ).collect(Collectors.toList());
    }
}
